home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hardcore Gamer Resource Kit
/
Hardcore Gamer Resource Kit - Disc 3.iso
/
screensavers
/
saver04.zip
/
track2.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-07-16
|
58KB
|
2,164 lines
#define GO
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include <time.h>
#include <string.h>
#include <search.h>
#include <glide.h>
#define Float2Int (int)
#define Int2Float (double)
#define BOTTOM 479
#define RIGHT 639
#define FOV 128
#define PI 3.141592654
#define TRUE 1
#define FALSE 0
#define TICK (double)0.3
#define DAMP (double)0.99
#define SLEEP 0
#define WATER 30
#define SURFACE 0
#define BLOB 1
#define MASK 2
#define CMASK 3
#define MAXVERTEX 750
#define MAXFACE 1400
extern short int VERTEX,FACE;
extern short int fobject[MAXVERTEX][3];
extern short int pt[MAXVERTEX][4],facet[MAXFACE][3],current_bin;
extern int facevert, facepoly;
extern void loadobject ();
int mode;
long sqrttab[0x100]; // declare table of square roots
long isqrttab[0x100]; // declare table of square roots
GrMipMapId_t facetexture,
texture1,
texture2,
texture3,
texture4,
texture5,
texture6,
spotlight,
cockpit;
GrMipMapId_t *fgtexture;
GrMipMapId_t *bgtexture;
GrHwConfiguration hwconfig;
GrColorCombineFnc_t cc_fnc;
GrScreenResolution_t screenRes;
float wWidth = 640.0f;
float wHeight = 480.0f;
double V [32][32];
double Fc [32][32]; /* Centering Force */
double Fn [32][32]; /* Neihboring Force */
typedef struct {
double x, y, z;
} point;
typedef struct {
point pt[3]; /* Vertices of triangle */
double area; /* Unused; might be used for adaptive subdivision */
} triangle;
typedef struct {
int npoly; /* # of triangles in object */
triangle *poly; /* Triangles */
} object;
int gid; /* Global Object id */
unsigned char *screen;
char screen_buff[640*480];
int max = 10;
unsigned int ADDR;
int width,height;
char filename[80];
int debug;
int count;
FILE* fp;
int bad;
/* Camera POV */
double cx,cy,cz;
int theta;
int ltheta;
int rtheta;
int ftheta;
double tpx,tpy; /* Test points */
double axl,byl,cl;
double axr,byr,cr;
double axf,byf,cf;
double lsign, rsign, fsign;
/*----- constants*/
#define MAXDEGREES 1024
#define EYE_DISTANCE Int2Fixed(256)
#define MAXVERTICES 2000
#define MAXPOLYGONS 2100
#define MAXPOLYVERT 3
double Fcb [MAXVERTICES];
double Vb [MAXVERTICES];
double Fnb [MAXVERTICES];
/*----- these are for the gouraud shading routines ----*/
int ledge_x[480]; /* x coordinate for left edge*/
int ledge_color[480]; /* color for left edge*/
int redge_x[480]; /* destination x coordinate for right edge*/
int redge_color[480]; /* color for right edge*/
/*----- these are for the basic graphics routines*/
int ytable[480]; /* so u can do ytable[y]+x (fast), instead of y*320+x (slow)*/
/*----- 16.16 fixedpoint trig lookup tables*/
double cosine[MAXDEGREES]; /* cosine lookup table*/
double sine[MAXDEGREES]; /* sine lookup table*/
double polar_lut [MAXDEGREES]; /* LUT for sin/cos theta near x-axis */
double dsine [MAXDEGREES];
double dcosine [MAXDEGREES];
/*----- angle and position of 3d object*/
int xangle,yangle,zangle; /* angles of rotation*/
double xpos,ypos,zpos; /* position of object in 3d*/
/* structure of one vertex*/
typedef struct
{
double s,t; /* Texture co-ordinates */
double ox,oy,oz; /* vertex original coordinates*/
double wx,wy,wz; /* vertex working coordinates*/
double Nox,Noy,Noz; /* vertex normal original coordinatesv*/
double SNox,SNoy,SNoz; /* vertex normal original coordinates - blob*/
double xlen,ylen,zlen;
int vcount;
double Nwx,Nwy,Nwz; /* vertex normal working coordinates*/
int sx,sy,sz; /* vertex screen coordinates*/
int color; /* color of vertex normal*/
} VertexTYPE;
/* structure of one polygon*/
typedef struct
{
int texture_type ; /* 0 = flat colour, 1 = Gouraud, 2 = Texture */
int NumOfVertices; /* number of vertices that make up the polygon*/
int Vertex[MAXPOLYVERT]; /* vertex indices in counter clockwise order*/
int zcenter; /* for sorting*/
double Nox,Noy,Noz; /* polygon normals (only used for ver normals)*/
} PolygonTYPE;
/* object structure*/
typedef struct
{
double Ox,Oy,Oz; /* coordinates of object's origin*/
int Ax,Ay,Az; /* object's rotation angles*/
int NumOfVertices; /* number of vertices in object*/
VertexTYPE Vertex[MAXVERTICES]; /* all vertices in object*/
int NumOfPolygons; /* number of polygons in object*/
PolygonTYPE Polygon[MAXPOLYGONS]; /* all polygons in object*/
} ObjectTYPE;
ObjectTYPE Object; /* one object - THIS IS THE WATER */
/* structure of light source*/
typedef struct
{
double x,y,z; /* coodinates of light source*/
double wx,wy,wz; /* working (intermediate) coordinates*/
int ax,ay,az; /* rotation angles*/
} LightSourceTYPE;
LightSourceTYPE LightSource; /* one light source*/
int NumOfSortedPolygons; /* number of sorted visible polygons*/
int NumOfViewedPolygons; /* number of sorted visible polygons*/
int PolygonOrderList[MAXPOLYGONS]; /* list of polygon indices for qsorting*/
int PolygonOrderClip[MAXPOLYGONS]; /* list of polygon indices for qsorting*/
int PolygonViewList[MAXPOLYGONS]; /* list of polygon indices in view */
int PolygonViewClip[MAXPOLYGONS]; /* list of polygon indices in view */
double xpath[MAXVERTICES];
double ypath[MAXVERTICES];
double zpath[MAXVERTICES];
int thetapath[MAXVERTICES];
/*---------------------- function prototypes ------------------------*/
int main(int argc,char**argv);
int Visible ();
void CalcViewTriangle();
void Demo();
void DrawGouraudPolygon(PolygonTYPE *poly);
void plot_tri_3dfx();
void plot_poly_3dfx();
void plot_bg();
void bench();
int Load3dfxTexture();
void InitYTable(void);
void InitTrigTables(void);
void ClearVertexList();
void Random();
void RotatePoints();
void RotateNormals();
void DrawObject();
void MakeViewPolygonList();
void MakeCulledPolygonList();
void SortPolygonList();
int _cdecl ComparePolygons(const void *a, const void *b);
void InitLightSource(void);
void CalculateColor();
void identity();
void multiply();
/*-------------------------------------------------------------------*/
int
DoFace()
{
object *obj;
int i,j,k,found;
double x,y,z;
double max=-99999.9,min=99999.9;
loadobject();
Object.NumOfVertices = 0;
Object.NumOfPolygons = 0;
for (i=0;i<MAXVERTICES;i++)
Object.Vertex[i].ox = 0;
/* For all poly's in list extract vertices */
for (i=0;i<facevert;i++)
{
z = (double)fobject[i][0]/4.0;
y = (double)fobject[i][1]/4.0;
x = (double)fobject[i][2]/4.0;
k = 0;
found = FALSE;
while (k<Object.NumOfVertices && found == FALSE)
{
if (Object.Vertex[k].ox == x &&
Object.Vertex[k].oy == y &&
Object.Vertex[k].oz == z )
found = TRUE;
else
k++;
}
/* add vertex to list */
if (found == FALSE)
{
Object.Vertex[k].ox = x;
Object.Vertex[k].oy = y;
Object.Vertex[k].oz = z;
Object.Vertex[k].s = 137.0 +(127.0/40.5) *z; /* Adjust height wise */
Object.Vertex[k].t = 201.0 +(127.0/37.0) * -x; /* Adjust width wise */
Object.NumOfVertices ++;
}
}
printf("Unique vertices = %d (%d) \n",
Object.NumOfVertices,3*facevert);
x = y = z = 0.0;
for (i=0;i<Object.NumOfVertices;i++)
{
x += Object.Vertex[i].ox;
y += Object.Vertex[i].oy;
z += Object.Vertex[i].oz;
}
x=x/(double)Object.NumOfVertices;
y=y/(double)Object.NumOfVertices;
z=z/(double)Object.NumOfVertices;
printf("Average = %f %f %f\n",x,y,z);
for (i=0;i<Object.NumOfVertices;i++)
{
Object.Vertex[i].ox-=x;
Object.Vertex[i].oy-=y;
Object.Vertex[i].oz-=z;
}
for (i=0;i<facepoly;i++)
{
Object.Polygon[i].Vertex[0] = facet[i][0];
Object.Polygon[i].Vertex[1] = facet[i][2];
Object.Polygon[i].Vertex[2] = facet[i][1];
Object.Polygon[i].NumOfVertices = 3;
Object.NumOfPolygons ++;
}
printf("Number of polys %d\n\n",Object.NumOfPolygons);
}
void
DoSphere(int level)
{
object *obj;
int i,j,k,found;
double x,y,z;
double maxx,minx;
maxx=-999.9;
minx=999.9;
obj = sphere(level);
Object.NumOfVertices = 0;
Object.NumOfPolygons = 0;
for (i=0;i<MAXVERTICES;i++)
Object.Vertex[i].ox = 0;
/* For all poly's in list extract vertices */
for (i=0;i<obj->npoly;i++)
{
for (j=0;j<3;j++)
{
x = obj->poly[i].pt[j].x*(double)20.0;
y = obj->poly[i].pt[j].y*(double)20.0;
z = obj->poly[i].pt[j].z*(double)20.0;
found = FALSE;
k = 0;
while (k<Object.NumOfVertices && found == FALSE)
{
if (Object.Vertex[k].ox == x &&
Object.Vertex[k].oy == y &&
Object.Vertex[k].oz == z )
found = TRUE;
else
k++;
}
/* add vertex to list */
if (found == FALSE)
{
Object.Vertex[k].ox = x;
Object.Vertex[k].oy = y;
Object.Vertex[k].oz = z;
Object.Vertex[k].s = 127.0 +(127.0/20.0) * x;
Object.Vertex[k].t = 127.0 +(127.0/20.0) * y;
if (x > maxx) maxx = x;
if (x< minx) minx = x;
Object.NumOfVertices ++;
}
}
}
printf("MAX %f MIN %f \n",maxx,minx);
printf("Unique vertices = %d (%d) \n",
Object.NumOfVertices,3*obj->npoly);
for (i=0;i<obj->npoly;i++)
{
for (j=0;j<3;j++)
{
x = obj->poly[i].pt[j].x*(double)20.0;
y = obj->poly[i].pt[j].y*(double)20.0;
z = obj->poly[i].pt[j].z*(double)20.0;
k = 0;found = FALSE;
while (k<Object.NumOfVertices && found == FALSE)
{
if (Object.Vertex[k].ox == x &&
Object.Vertex[k].oy == y &&
Object.Vertex[k].oz == z )
found = TRUE;
else
k++;
}
if (k == Object.NumOfVertices) printf("OH DEAR!\n");
Object.Polygon[i].Vertex[j] = k;
}
Object.Polygon[i].NumOfVertices = 3;
}
Object.NumOfPolygons = i;
printf("Number of polys %d\n\n",Object.NumOfPolygons);
}
void build_table(void) {
unsigned short i;
float f;
unsigned int *fi = (unsigned*)&f; // To access the bits of a float in
// C quickly we must misuse pointers
for (i = 0; i <= 0x7f; i++) {
*fi = 0;
// Build a float with the bit pattern i as mantissa
// and an exponent of 0, stored as 127
*fi = (i << 16) | (127 << 23);
f = sqrt(f);
// Take the square root then strip the first 7 bits of
// the mantissa into the table
sqrttab[i] = (*fi & 0x7fffff);
// Repeat the process, this time with an exponent of 1,
// stored as 128
*fi = 0;
*fi = (i << 16) | (128 << 23);
f = sqrt(f);
sqrttab[i+0x80] = (*fi & 0x7fffff);
}
}
void build_itable(void) {
unsigned short i;
float f;
unsigned int *fi = (unsigned*)&f; // To access the bits of a float in
// C quickly we must misuse pointers
for (i = 0; i <= 0x7f; i++) {
*fi = 0;
// Build a float with the bit pattern i as mantissa
// and an exponent of 0, stored as 127
*fi = (i << 16) | (127 << 23);
f = 1.0/sqrt(f);
// Take the square root then strip the first 7 bits of
// the mantissa into the table
isqrttab[i] = (*fi & 0x7fffff);
// Repeat the process, this time with an exponent of 1,
// stored as 128
*fi = 0;
*fi = (i << 16) | (128 << 23);
f = 1.0/sqrt(f);
isqrttab[i+0x80] = (*fi & 0x7fffff);
}
}
// fsqrt - fast square root by table lookup, original C version
float fsqrt(float n) {
unsigned int *num = (unsigned *)&n; // to access the bits of a float in C
// we must misuse pointers
short e; // the exponent
if (n == 0) return (0); /* check for square root of 0 */
e = (*num >> 23) - 127; /* get the exponent - on a SPARC the */
/* exponent is stored with 127 added */
*num &= 0x7fffff; /* leave only the mantissa */
if (e & 0x01) *num |= 0x800000;
/* the exponent is odd so we have to */
/* look it up in the second half of */
/* the lookup table, so we set the high bit */
e >>= 1; /* divide the exponent by two */
/* note that in C the shift */
/* operators are sign preserving */
/* for signed operands */
// Do the table lookup, based on the quaternary mantissa,
// then reconstruct the result back into a float
*num = ((sqrttab[*num >> 16])) + ((e + 127) << 23);
return(n);
}
float fisqrt(float n) {
unsigned int *num = (unsigned *)&n; // to access the bits of a float in C
// we must misuse pointers
short e; // the exponent
if (n == 0) return (0); /* check for square root of 0 */
e = (*num >> 23) - 127; /* get the exponent - on a SPARC the */
/* exponent is stored with 127 added */
*num &= 0x7fffff; /* leave only the mantissa */
if (e & 0x01) *num |= 0x800000;
/* the exponent is odd so we have to */
/* look it up in the second half of */
/* the lookup table, so we set the high bit */
e >>= 1; /* divide the exponent by two */
/* note that in C the shift */
/* operators are sign preserving */
/* for signed operands */
// Do the table lookup, based on the quaternary mantissa,
// then reconstruct the result back into a float
*num = ((isqrttab[*num >> 16])) + ((e + 127) << 23);
return(n);
}
int
init()
{
int x,y,i;
for (x = 0; x< WATER; x++)
{
for (y=0; y<WATER; y++)
{
V [x][y] = 0.0;
}
}
for (x = 0; x< Object.NumOfVertices; x++)
Vb [x] = 0.0;
Vb[rand()%Object.NumOfVertices] = 7.0;
Vb[rand()%Object.NumOfVertices] = 7.0;
Vb[rand()%Object.NumOfVertices] = 7.0;
Vb[rand()%Object.NumOfVertices] = 7.0;
Vb[rand()%Object.NumOfVertices] = 7.0;
Vb[rand()%Object.NumOfVertices] = 7.0;
V[WATER/2][WATER/2] = 8.0;
V[WATER/2-1][WATER/2] = 8.0;
V[WATER/2-1][WATER/2-1] = 8.0;
V[WATER/2][WATER/2-1] = 8.0;
/*V[15][15] = 5.0;*/
}
int
calcFc(int mode)
{
int x,y;
double max,roottwo;
roottwo = 1.0 / sqrt(2.0);
max = -99999.99;
if (mode == SURFACE)
{
for (x = 0; x< WATER; x++)
{
for (y=0; y<WATER; y++)
{
/*Fc [x][y] = Object.Vertex[x+y*WATER].ox /15.0;
Fc [x][y] = 0.1*fabs(Object.Vertex[x+y*WATER].ox) * Object.Vertex[x+y*WATER].ox;*/
Fc [x][y] = Object.Vertex[x+y*WATER].ox;
}
}
for (x = 1; x< WATER; x++)
{
for (y=1; y<WATER; y++)
{
Fn [x][y]=(roottwo*Fc[x-1][y-1]) + Fc[x][y-1] + (roottwo*Fc[x+1][y-1])+
Fc[x-1][y] + 0.0*Fc[x][y] + Fc[x+1][ y] +
(roottwo*Fc[x-1][y+1]) + Fc[x][y+1] + (roottwo*Fc[x+1][y+1]) ;
Fn [x][y] = Fn [x][y]/(4.0+roottwo*4.0);
V[x][y] += TICK * (Fn[x][y] - Fc[x][y]) /* Accel */;
V[x][y] *= DAMP; /* Damping */
Object.Vertex[x+y*WATER].ox+=TICK * V[x][y];
}
}
}
else if (mode == BLOB)
{
for (x = Object.NumOfVertices-1; x>=0; x--)
{
Fcb [x] = sqrt(Object.Vertex[x].ox*Object.Vertex[x].ox +
Object.Vertex[x].oy*Object.Vertex[x].oy +
Object.Vertex[x].oz*Object.Vertex[x].oz );
Object.Vertex[x].vcount = 0.0;
Fnb [x] = 0.0;
}
/* for each polygon .. */
for (x = Object.NumOfPolygons-1; x>=0; x--)
{
for (y=2;y>=0;y--) /* for each vertex */
{
Fnb [Object.Polygon[x].Vertex[y]] +=
(Fcb[Object.Polygon[x].Vertex[(y+1)%3]] +
Fcb[Object.Polygon[x].Vertex[(y+2)%3]])/2.0 ;
/* printf("Poly %d Vertex %d (%d) = %f\n",
x,y,Object.Polygon[x].Vertex[y],
Fnb [Object.Polygon[x].Vertex[y]]) ; */
Object.Vertex[Object.Polygon[x].Vertex[y]].vcount += 1.0;
}
}
for (x = Object.NumOfVertices-1; x>=0; x--)
{
Fnb [x] = Fnb [x] / Object.Vertex[x].vcount ;
/*
printf("Fnb[%d] = %f / %f = %f\n",
x,Fnb[x],Object.Vertex[x].vcount,
Fnb[x]);
*/
/* printf("Fnb = %lf Fcb = %lf\n",
Fnb[x],Fcb[x]); */
Vb[x] += TICK * (Fnb[x] - Fcb[x]) /* Accel */;
Vb[x] *= DAMP; /* Damping */
Object.Vertex[x].ox+= Object.Vertex[x].ox * ((TICK * Vb[x])/Fnb[x]);
Object.Vertex[x].oy+= Object.Vertex[x].oy * ((TICK * Vb[x])/Fnb[x]);
Object.Vertex[x].oz+= Object.Vertex[x].oz * ((TICK * Vb[x])/Fnb[x]);
}
}
}
/*----------------------------------------------------------------------*/
void InitTrigTables(void)
{
int i;
for(i=0; i<MAXDEGREES; i++)
{
cosine[i]=(cos((double)i*(double)360/MAXDEGREES *
(double)3.14159265 /(double)180.0));
sine[i] =(sin((double)i*(double)360/MAXDEGREES *
(double)3.14159265 / (double)180.0));
dsine[i] = (sin((double)i*(double)360/MAXDEGREES *
(double)PI/(double)180.0));
dcosine[i] = (cos((double)i*(double)360/MAXDEGREES *
(double)PI/(double)180.0));
if (qabs(256-i)>128 &&
qabs(768-i)>128)
polar_lut[i] = (sin((double)i*(double)360/MAXDEGREES *
(double)PI/(double)180.0)) /
(cos((double)i*(double)360/MAXDEGREES *
(double)PI/(double)180.0));
else
polar_lut[i] = (cos((double)i*(double)360/MAXDEGREES *
(double)PI /(double)180.0)) /
(sin((double)i*(double)360/MAXDEGREES *
(double)PI/(double)180.0));
}
}
void InitYTable(void)
{
int i;
for(i=0;i<480;i++)
{
ytable[i]=i*640;
}
}
/*----------------------------------------------------------------------*/
void FInitNormals()
{
register double x1,x2,x3,y1,y2,y3,z1,z2,z3,length;
register double xlen,ylen,zlen;
register int i,j,k;
/*printf(" first calculate the polygon normals\n"); */
for(i = Object.NumOfPolygons-1;i>=0 ;i--)
{
x1=(Object.Vertex[Object.Polygon[i].Vertex[0]].ox);
x2=(Object.Vertex[Object.Polygon[i].Vertex[1]].ox);
x3=(Object.Vertex[Object.Polygon[i].Vertex[2]].ox);
y1=(Object.Vertex[Object.Polygon[i].Vertex[0]].oy);
y2=(Object.Vertex[Object.Polygon[i].Vertex[1]].oy);
y3=(Object.Vertex[Object.Polygon[i].Vertex[2]].oy);
z1=(Object.Vertex[Object.Polygon[i].Vertex[0]].oz);
z2=(Object.Vertex[Object.Polygon[i].Vertex[1]].oz);
z3=(Object.Vertex[Object.Polygon[i].Vertex[2]].oz);
/* calculate perpendicular via the cross product of 1st vertex & normal*/
xlen = (y1-y2)*(z1-z3) - (z1-z2)*(y1-y3);
ylen = (z1-z2)*(x1-x3) - (x1-x2)*(z1-z3);
zlen = (x1-x2)*(y1-y3) - (y1-y2)*(x1-x3);
/* calculate the length of the normal*/
length = 1.0/sqrt(xlen*xlen + ylen*ylen + zlen*zlen);
/* scale it to a unit normal*/
if (length!=0.0)
{
Object.Polygon[i].Nox = (xlen * length);
Object.Polygon[i].Noy = (ylen * length);
Object.Polygon[i].Noz = (zlen * length);
}
}
/*This will calculate the normals of the vertices for environment mapping*/
for(i= Object.NumOfVertices-1;i>=0; i--)
{
Object.Vertex[i].xlen = 0.0;
Object.Vertex[i].ylen = 0.0;
Object.Vertex[i].zlen = 0.0;
Object.Vertex[i].vcount = 0;
}
for(j = Object.NumOfPolygons-1;j>=0 ;j--)
{
for(k=Object.Polygon[j].NumOfVertices-1;k>=0;k--)
{
Object.Vertex[Object.Polygon[j].Vertex[k]].xlen += Object.Polygon[j].Nox;
Object.Vertex[Object.Polygon[j].Vertex[k]].ylen += Object.Polygon[j].Noy;
Object.Vertex[Object.Polygon[j].Vertex[k]].zlen += Object.Polygon[j].Noz;
Object.Vertex[Object.Polygon[j].Vertex[k]].vcount ++;
}
}
for(i= Object.NumOfVertices-1;i>=0; i--)
{
if(Object.Vertex[i].vcount >0)
{
Object.Vertex[i].xlen=Object.Vertex[i].xlen/(double)Object.Vertex[i].vcount;
Object.Vertex[i].ylen=Object.Vertex[i].ylen/(double)Object.Vertex[i].vcount;
Object.Vertex[i].zlen=Object.Vertex[i].zlen/(double)Object.Vertex[i].vcount;
}
length = 1.0/sqrt(Object.Vertex[i].xlen*Object.Vertex[i].xlen +
Object.Vertex[i].ylen*Object.Vertex[i].ylen +
Object.Vertex[i].zlen*Object.Vertex[i].zlen );
if (length !=0.0)
{
Object.Vertex[i].Nox = (Object.Vertex[i].xlen * length);
Object.Vertex[i].Noy = (Object.Vertex[i].ylen * length);
Object.Vertex[i].Noz = (Object.Vertex[i].zlen * length);
}
}
}
void InitNormals()
{
register double x1,x2,x3,y1,y2,y3,z1,z2,z3,length;
register double xlen,ylen,zlen;
register int i,j,k;
/*printf(" first calculate the polygon normals\n"); */
for(i = Object.NumOfPolygons-1;i>=0 ;i--)
{
x1=(Object.Vertex[Object.Polygon[i].Vertex[0]].ox);
x2=(Object.Vertex[Object.Polygon[i].Vertex[1]].ox);
x3=(Object.Vertex[Object.Polygon[i].Vertex[2]].ox);
y1=(Object.Vertex[Object.Polygon[i].Vertex[0]].oy);
y2=(Object.Vertex[Object.Polygon[i].Vertex[1]].oy);
y3=(Object.Vertex[Object.Polygon[i].Vertex[2]].oy);
z1=(Object.Vertex[Object.Polygon[i].Vertex[0]].oz);
z2=(Object.Vertex[Object.Polygon[i].Vertex[1]].oz);
z3=(Object.Vertex[Object.Polygon[i].Vertex[2]].oz);
/* calculate perpendicular via the cross product of 1st vertex & normal*/
xlen = (y1-y2)*(z1-z3) - (z1-z2)*(y1-y3);
ylen = (z1-z2)*(x1-x3) - (x1-x2)*(z1-z3);
zlen = (x1-x2)*(y1-y3) - (y1-y2)*(x1-x3);
/* calculate the length of the normal*/
length = 1.0/sqrt(xlen*xlen + ylen*ylen + zlen*zlen);
/* scale it to a unit normal*/
if (length!=0.0)
{
Object.Polygon[i].Nox = (xlen * length);
Object.Polygon[i].Noy = (ylen * length);
Object.Polygon[i].Noz = (zlen * length);
}
}
/*This will calculate the normals of the vertices for environment mapping*/
for(i= Object.NumOfVertices-1;i>=0; i--)
{
Object.Vertex[i].xlen = 0.0;
Object.Vertex[i].ylen = 0.0;
Object.Vertex[i].zlen = 0.0;
Object.Vertex[i].vcount = 0;
}
for(j = Object.NumOfPolygons-1;j>=0 ;j--)
{
for(k=Object.Polygon[j].NumOfVertices-1;k>=0;k--)
{
Object.Vertex[Object.Polygon[j].Vertex[k]].xlen += Object.Polygon[j].Nox;
Object.Vertex[Object.Polygon[j].Vertex[k]].ylen += Object.Polygon[j].Noy;
Object.Vertex[Object.Polygon[j].Vertex[k]].zlen += Object.Polygon[j].Noz;
Object.Vertex[Object.Polygon[j].Vertex[k]].vcount ++;
}
}
for(i= Object.NumOfVertices-1;i>=0; i--)
{
if(Object.Vertex[i].vcount >0)
{
Object.Vertex[i].xlen=Object.Vertex[i].xlen/(double)Object.Vertex[i].vcount;
Object.Vertex[i].ylen=Object.Vertex[i].ylen/(double)Object.Vertex[i].vcount;
Object.Vertex[i].zlen=Object.Vertex[i].zlen/(double)Object.Vertex[i].vcount;
}
length = 1.0/sqrt(Object.Vertex[i].xlen*Object.Vertex[i].xlen +
Object.Vertex[i].ylen*Object.Vertex[i].ylen +
Object.Vertex[i].zlen*Object.Vertex[i].zlen );
if (length !=0.0)
{
Object.Vertex[i].SNox = (Object.Vertex[i].xlen * length);
Object.Vertex[i].SNoy = (Object.Vertex[i].ylen * length);
Object.Vertex[i].SNoz = (Object.Vertex[i].zlen * length);
}
}
}
void RotateNormals()
{
int i;
double nx,ny,nz,cosxangle,sinxangle,cosyangle,
sinyangle,coszangle,sinzangle;
VertexTYPE *vert; /* pointer to a vertex structure*/
/* get sine and cosine angles to save time from table lookup in inner loop*/
sinxangle=sine[xangle];
cosxangle=cosine[xangle];
sinyangle=sine[yangle];
cosyangle=cosine[yangle];
sinzangle=sine[zangle];
coszangle=cosine[zangle];
for(i=0;i<Object.NumOfVertices;i++)
{
vert=&Object.Vertex[i];
/* rotate around the x-axis */
vert->Nwz=(vert->Noy * cosxangle) - (vert->Noz * sinxangle);
vert->Nwy=(vert->Noy * sinxangle) + (vert->Noz * cosxangle);
vert->Nwx=vert->Nox;
/* rotate around the y-axis */
vert->Nwx = (vert->Nwx * cosyangle) - (vert->Nwz * sinyangle);
nz = (vert->Nwx * sinyangle) + (vert->Nwz * cosyangle);
vert->Nwz=nz;
/* rotate around the z-axis */
nx=(vert->Nwx * coszangle) - (vert->Nwy * sinzangle);
ny=(vert->Nwx * sinzangle) + (vert->Nwy * coszangle);
/* reverse the direction of the normals for lightsource shading*/
vert->Nwx=nx; vert->Nwy=ny; vert->Nwz=nz;
}
}
/*-------------------------- calculate color of vertex normal ----------*/
void DrawGouraudPolygon(PolygonTYPE *poly)
{
/*Plot a triangle!*/
printf("?\n");
if (poly->NumOfVertices ==3 /*&& CHROME MASK mode != MASK*/)
{
plot_tri_3dfx(poly);
}
else
{
plot_poly_3dfx(poly);
}
}
void MakePolygonList()
{
int i,j;
VertexTYPE *v0,*v1,*v2;
j=0;
for(i=0;i<Object.NumOfPolygons;i++)
{
v0=&Object.Vertex[Object.Polygon[i].Vertex[0]];
v1=&Object.Vertex[Object.Polygon[i].Vertex[1]];
v2=&Object.Vertex[Object.Polygon[i].Vertex[2]];
/* if expression results in a negative then polygon is visible
if( ((v1->sx - v0->sx) * (v2->sy - v0->sy) - (v1->sy - v0->sy) * (v2->sx - v0->sx)) < 0 )
{
PolygonOrderList[j++]=i;
}*/
PolygonOrderList[j++]=i; /* all polys visible */
}
NumOfSortedPolygons=j;
}
void CalculateColor()
{
int i;
int color;
double DotProduct,t1,t2;
for(i=0; i < Object.NumOfVertices; i++)
{
DotProduct= Object.Vertex[i].Nwx * LightSource.x;
t1= Object.Vertex[i].Nwy * LightSource.y;
t2= Object.Vertex[i].Nwz * LightSource.z;
DotProduct += (t1 + t2);
t1=DotProduct * 64.0 ;
Object.Vertex[i].color = 80.0 + t1;
}
}
void RotatePoints()
{
int i;
double nx,ny,nz,cosxangle,sinxangle,
cosyangle,sinyangle,coszangle,sinzangle;
double t1, t2, t3;
/* get the sine and cosine angles to save time from table lookup*/
sinxangle=sine[xangle]; /* Pitch */
cosxangle=cosine[xangle];
sinyangle=sine[yangle]; /* Yaw */
cosyangle=cosine[yangle];
sinzangle=sine[zangle]; /* Roll */
coszangle=cosine[zangle];
/* loop through all vertices in object*/
for(i=0;i<Object.NumOfVertices;i++)
{
/* make a pointer to the current vertex*/
VertexTYPE *vert=&Object.Vertex[i];
/* rotate around the x-axis*/
vert->wz= ((vert->oy-cy)*cosxangle)-((vert->oz-cz)*sinxangle);
vert->wy= ((vert->oy-cy)*sinxangle)+((vert->oz-cz)*cosxangle);
vert->wx=vert->ox-cx;
/*comment out above line and stick this one in to
see just how good env. mapping can be :)
vert->wx=0.0-cx; */
/* rotate around the y-axis */
nx = (vert->wx*cosyangle)-(vert->wz*sinyangle);
nz = (vert->wx*sinyangle)+(vert->wz*cosyangle);
vert->wx=nx;
vert->wz=nz;
/* rotate around the z-axis*/
nx = (vert->wx*coszangle)-(vert->wy*sinzangle);
ny = (vert->wx*sinzangle)+(vert->wy*coszangle);
vert->wx=nx;
vert->wy=ny;
/* project the 3-D coordinates to screen coordinates*/
t3 = vert->wz+zpos;
if (t3<0.00 )
{
vert->sx =(int)(((vert->wx+xpos)/t3)* /*256.0*/ 512.0)+320;
vert->sy =220-(int)(((vert->wy+ypos)/t3)* /*256.0*/ 512.0);
}
else
{ /* ooh negative z!*/
t3 = -1.0;
t3 = -0.1;
t3 = 1.0+ t3;
vert->sx =(int)(((vert->wx+xpos)*t3)*512.0)+320;
vert->sy =(int)(((vert->wy+ypos)*t3)*512.0)+220;
}
vert->sz=(int)(vert->wz+zpos);
vert->sz=(int)t3;
}
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
void DrawObject()
{
int i;
fprintf(fp,"make poly list\n");
MakeCulledPolygonList();
fprintf(fp,"sort poly list\n");
SortPolygonList();
fprintf(fp,"calc colour\n");
CalculateColor();
/**/
guAlphaSource( GR_ALPHASOURCE_ITERATED_ALPHA );
grAlphaBlendFunction( GR_BLEND_SRC_ALPHA,
GR_BLEND_ONE_MINUS_SRC_ALPHA,
GR_BLEND_ONE,
GR_BLEND_ZERO );
grAlphaTestFunction( GR_CMP_ALWAYS );
guColorCombineFunction(GR_COLORCOMBINE_DECAL_TEXTURE);
if (mode == MASK ) /* Turn face on here */
guTexSource( facetexture );
else
guTexSource( *fgtexture );
grTexCombineFunction(GR_TMU0, GR_TEXTURECOMBINE_DECAL);
/**/
for(i=0;i<NumOfSortedPolygons;i++)
{
if (mode != CMASK)
plot_tri_3dfx(&Object.Polygon[PolygonOrderList[i]]);
else
plot_poly_3dfx(&Object.Polygon[PolygonOrderList[i]]);
}
}
int
swapbuffer()
{
while(grBufferNumPending());
grBufferSwap(0);
guColorCombineFunction( GR_COLORCOMBINE_ITRGB );
/* Thi renders a background image */
plot_bg();/**/
/* Or use this to simply clear the screen - twice as fast o/
grBufferClear( 0xFF223344, 0, GR_WDEPTHVALUE_FARTHEST );/**/
}
void
Random ()
{
int i,j;
int pindex;
int z;
double xf,yf,zf;
Object.NumOfVertices = 0;
for (i=0;i<MAXVERTICES;i++)
{
Object.Vertex[i].ox = 99999;
}
Object.NumOfVertices=0;
for (i=0;i<WATER;i++)
{
for (j=0;j<WATER;j++)
{
z = 0;
Object.Vertex[i+j*WATER].oy=(double)(i*2.5);
Object.Vertex[i+j*WATER].oz=(double)(j*2.5);
Object.Vertex[i+j*WATER].ox=(double)(z);
Object.Vertex[i+j*WATER].s = (255.0/(double)WATER)*(double)j;
Object.Vertex[i+j*WATER].t = (255.0/(double)WATER)*(double)i;
Object.NumOfVertices++;
}
}
printf("Object.NumOfVertices=%d\n",Object.NumOfVertices);
pindex=0;
for (i=1;i<WATER;i++)
{
for (j=1;j<WATER;j++)
{ /* Try is clockwise...*/
Object.Polygon[pindex].Vertex[0] = (j-1)+(i-1)*WATER;
Object.Polygon[pindex].Vertex[2] = (j)+(i)*WATER;
Object.Polygon[pindex].Vertex[1] = (j)+(i-1)*WATER;
Object.Polygon[pindex].Vertex[3] = 99999;
Object.Polygon[pindex].NumOfVertices = 3;
pindex++;
Object.Polygon[pindex].Vertex[0] = (j-1)+(i-1)*WATER;
Object.Polygon[pindex].Vertex[2] = (j-1)+(i)*WATER;
Object.Polygon[pindex].Vertex[1] = (j)+(i)*WATER;
Object.Polygon[pindex].Vertex[3] = 99999;
Object.Polygon[pindex].NumOfVertices = 3;
pindex++;
}
}
Object.NumOfPolygons=pindex;
printf("Object.NumOfPolygons=%d\n",Object.NumOfPolygons);
xf=0.0;yf=0.0;zf=0.0;
for (i=0;i<MAXVERTICES;i++)
{
if (Object.Vertex[i].ox==99999) break;
xf = xf + (double) Object.Vertex[i].ox;
yf = yf + (double) Object.Vertex[i].oy;
zf = zf + (double) Object.Vertex[i].oz;
}
xf = xf / (double)i; yf = yf / (double)i; zf = zf / (double)i;
printf("Average = %f %f %f\n",xf,yf,zf);
for (i=0;i<MAXVERTICES;i++)
{
if (Object.Vertex[i].ox==99999) break;
Object.Vertex[i].ox = Object.Vertex[i].ox - (int)xf;
Object.Vertex[i].oy = Object.Vertex[i].oy - (int)yf;
Object.Vertex[i].oz = Object.Vertex[i].oz - (int)zf;
}
}
/*----------------------------------------------------------*/
/*----------------------------------------------------------*/
void ClearVertexList()
{
int i;
Object.NumOfVertices = 0;
for (i=0;i<MAXVERTICES;i++)
{
Object.Vertex[i].ox = 99999;
}
}
/*---------------------- draw gouraud polygon ------------------------------*/
int
Load3dfxTexture(char *texfile, GrMipMapId_t *texture)
{
Gu3dfInfo info;
/* Load Texture */
if ( !gu3dfGetInfo( texfile, &info ) )
{
fprintf(stderr, "ERROR: could not load %s\n",texfile);
grGlideShutdown();
exit( -1 );
}
else
{
info.data = malloc( info.mem_required );
if ( info.data == 0 ) {
fprintf( stderr, "out of memory for texture\n" );
grGlideShutdown();
exit( -1 );
}
if ( !gu3dfLoad(texfile, &info ) ) {
fprintf( stderr, "could not load texture file\n" );
grGlideShutdown();
exit( -1 );
}
*texture = guTexAllocateMemory( 0, GR_MIPMAPLEVELMASK_BOTH,
info.header.width, info.header.height,
info.header.format,
GR_MIPMAP_NEAREST,
info.header.small_lod, info.header.large_lod,
info.header.aspect_ratio,
GR_TEXTURECLAMP_WRAP, GR_TEXTURECLAMP_WRAP,
GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR,
0.0F,
FXFALSE );
if ( *texture == GR_NULL_MIPMAP_HANDLE ) {
fprintf( stderr, "could not allocate memory for lava.3df\n" );
grGlideShutdown();
exit( -1 );
}
guTexDownloadMipMap(*texture, info.data, &info.table.nccTable );
free( info.data );
}
return(0);
}
void bench ()
{
GrVertex vtx1, vtx2, vtx3;
int i;
clock_t tim;
vtx1.x=100.f; vtx1.y=100.f;
vtx2.x=200.f; vtx2.y=100.f;
vtx3.x=150.f; vtx3.y=150.f;
vtx1.r=189.f; vtx2.r=10.f; vtx3.r=99.f;
vtx1.g=2.f; vtx2.g=255.f; vtx3.g=77.f;
vtx1.b=5.f; vtx2.b=222.f; vtx3.b=199.f;
vtx1.a=220.0f; vtx2.a=220.0f; vtx3.a=220.0f;
tim=clock();
for (i=0;i<5000;i++)
grDrawTriangle( &vtx1, &vtx2, &vtx3 );
tim=clock()-tim;
grBufferSwap(0);
while(!kbhit());
printf("Elapsed = %lf seconds\n",(double)(tim)/CLOCKS_PER_SEC);
printf("%f tris/sec\n",5000.0f/((double)(tim)/CLOCKS_PER_SEC));
}
void plot_bg()
{
static int rot = 0;
double tx, ty;
GrVertex vlist[4];
rot = (rot++) % (MAXDEGREES-1);
tx = sine[rot]*128.0;
ty = cosine[rot]*128.0;
vlist[0].x = 0.f;
vlist[0].y = 0.f;
vlist[0].r=128.0f;
vlist[0].g=0.0f;
vlist[0].b=0.0f;
vlist[0].a=255.0f;
vlist[1].x = 640.f;
vlist[1].y = 0.f;
vlist[1].r=200.0f;
vlist[1].g=0.0f;
vlist[1].b=0.0f;
vlist[1].a=255.0f;
vlist[2].x = 0.f;
vlist[2].y = 480.f;
vlist[2].r=55.0f;
vlist[2].g=0.0f;
vlist[2].b=0.0f;
vlist[2].a=255.0f;
vlist[3].x = 640.f;
vlist[3].y = 480.f;
vlist[3].r=100.0f;
vlist[3].g=0.0f;
vlist[3].b=0.0f;
vlist[3].a=255.0f;
vlist[0].oow=1.f/2000.0f;
vlist[1].oow=1.f/2000.0f;
vlist[2].oow=1.f/2000.0f;
vlist[3].oow=1.f/2000.0f;
vlist[0].tmuvtx[0].sow = (tx+128.0) * vlist[0].oow;
vlist[0].tmuvtx[0].tow = (ty+128.0) * vlist[0].oow;
vlist[1].tmuvtx[0].sow = (128.0-ty) * vlist[1].oow;
vlist[1].tmuvtx[0].tow = (tx+128.0) * vlist[1].oow;
vlist[2].tmuvtx[0].sow = (ty+128.0) * vlist[2].oow;
vlist[2].tmuvtx[0].tow = (128.0-tx) * vlist[2].oow;
vlist[3].tmuvtx[0].sow = (128.0-tx) * vlist[3].oow;
vlist[3].tmuvtx[0].tow = (128.0-ty) * vlist[3].oow;
guColorCombineFunction(GR_COLORCOMBINE_DECAL_TEXTURE);
guTexSource( *bgtexture );
grTexCombineFunction(GR_TMU0, GR_TEXTURECOMBINE_DECAL);
/* hmm do bias bit .. */
grDrawTriangle(&vlist[0],&vlist[1],&vlist[2]);
grDrawTriangle(&vlist[1],&vlist[3],&vlist[2]);
guColorCombineFunction( GR_COLORCOMBINE_ITRGB );
}
void plot_poly_3dfx (PolygonTYPE *poly)
{
GrVertex vlist[255];
GrState state;
int i;
float sow[4],tow[4];
float s,t;
sow[0] = 0.0f;tow[0]=0.0f;
sow[1] = 255.0f;tow[1]=0.0f;
sow[2] = 255.0f;tow[2]=255.0f;
sow[3] = 0.0f;tow[3]=255.0f;
for (i=0;i<poly->NumOfVertices;i++)
{
vlist[i].x=(float)Object.Vertex[poly->Vertex[i]].sx;
vlist[i].y=(float)Object.Vertex[poly->Vertex[i]].sy;
vlist[i].r=(float)Object.Vertex[poly->Vertex[i]].color;
vlist[i].g=(float)Object.Vertex[poly->Vertex[i]].color*0.f;
vlist[i].b=(float)Object.Vertex[poly->Vertex[i]].color*0.f;
vlist[i].a=255.0f;
/*vlist[i].a=(float)Object.Vertex[poly->Vertex[i]].color;*/
vlist[i].oow = -1.f/(float)Object.Vertex[poly->Vertex[i]].sz;
/*
vlist[i].tmuvtx[0].sow = sow[i % 4] * vlist[i].oow;
vlist[i].tmuvtx[0].tow = tow[i % 4] * vlist[i].oow;
*/
Object.Vertex[poly->Vertex[i]].s = 127.0 +(127.0/20.0) *
Object.Vertex[poly->Vertex[i]].wx; /* Adjust height wise */
Object.Vertex[poly->Vertex[i]].t = 127.0 +(127.0/20.0) *
-Object.Vertex[poly->Vertex[i]].wy; /* Adjust width wise */
vlist[i].tmuvtx[0].sow =
(Object.Vertex[poly->Vertex[i]].s - 40.0*Object.Vertex[poly->Vertex[i]].Nox)
* vlist[i].oow;
vlist[i].tmuvtx[0].tow =
(Object.Vertex[poly->Vertex[i]].t - 40.0*Object.Vertex[poly->Vertex[i]].Noy)
* vlist[i].oow;
/*
vlist[i].tmuvtx[0].sow =
(Object.Vertex[poly->Vertex[i]].s + 40.0*
(Object.Vertex[poly->Vertex[i]].SNox+Object.Vertex[poly->Vertex[i]].Nox))
* vlist[i].oow;
vlist[i].tmuvtx[0].tow =
(Object.Vertex[poly->Vertex[i]].t + 40.0*
(Object.Vertex[poly->Vertex[i]].SNoy+Object.Vertex[poly->Vertex[i]].Noy))
* vlist[i].oow;*/
/*
vlist[i].tmuvtx[0].sow = (Object.Vertex[poly->Vertex[i]].s) * vlist[i].oow;
vlist[i].tmuvtx[0].tow = (Object.Vertex[poly->Vertex[i]].t) * vlist[i].oow;
*/
if (vlist[i].x > 640 ||
vlist[i].x <0 ||
vlist[i].y >480 ||
vlist[i].y <0 ) return;
}
#ifdef GO
grDrawPlanarPolygonVertexList(poly->NumOfVertices,vlist);
/*guColorCombineFunction( GR_COLORCOMBINE_ITRGB );*/
#endif
/* save state! */
grGlideGetState(&state);
/* projected textrure :( */
for (i=0;i<poly->NumOfVertices;i++)
{
s = (20.0f * vlist[i].oow)*(vlist[i].x - 320.0f) ;
t = (20.0f * vlist[i].oow)*(240.0f - vlist[i].y) ;
s = (s+320.0f)/2.5098f;
t = (t+240.0f)/1.8824f;
vlist[i].tmuvtx[0].sow = s * vlist[i].oow;
vlist[i].tmuvtx[0].tow = t * vlist[i].oow;
vlist[i].tmuvtx[0].oow = 20.0f * vlist[i].oow;
}
#ifdef GO
guColorCombineFunction(GR_COLORCOMBINE_DECAL_TEXTURE);
grAlphaBlendFunction(GR_BLEND_ONE,GR_BLEND_ONE,
GR_BLEND_ONE,GR_BLEND_ZERO);
guTexSource( spotlight);
grTexCombineFunction(GR_TMU0, GR_TEXTURECOMBINE_DECAL);
grDrawPlanarPolygonVertexList(poly->NumOfVertices,vlist);
#endif
/* restore state */
grGlideSetState(&state);
}
/*???*/
void plot_tri_3dfx (PolygonTYPE *poly)
{
GrVertex vtx1, vtx2, vtx3;
GrState state ;
float s,t;
long tmp;
vtx1.x=(float)Object.Vertex[poly->Vertex[0]].sx;
vtx1.y=(float)Object.Vertex[poly->Vertex[0]].sy;
vtx2.x=(float)Object.Vertex[poly->Vertex[1]].sx;
vtx2.y=(float)Object.Vertex[poly->Vertex[1]].sy;
vtx3.x=(float)Object.Vertex[poly->Vertex[2]].sx;
vtx3.y=(float)Object.Vertex[poly->Vertex[2]].sy;
vtx1.r=(float)Object.Vertex[poly->Vertex[0]].ox*20.0+128.0;
vtx2.r=(float)Object.Vertex[poly->Vertex[1]].ox*20.0+128.0;
vtx3.r=(float)Object.Vertex[poly->Vertex[2]].ox*20.0+128.0;
vtx1.g=(float)Object.Vertex[poly->Vertex[0]].ox*20.0+128.0;
vtx2.g=(float)Object.Vertex[poly->Vertex[1]].ox*20.0+128.0;
vtx3.g=(float)Object.Vertex[poly->Vertex[2]].ox*20.0+128.0;
vtx1.b=(float)Object.Vertex[poly->Vertex[0]].ox*20.0+128.0;
vtx2.b=(float)Object.Vertex[poly->Vertex[1]].ox*20.0+128.0;
vtx3.b=(float)Object.Vertex[poly->Vertex[2]].ox*20.0+128.0;
/* SNAP */
tmp = vtx1.x * 16; // increase by 4 bits, truncate off the rest
vtx1.x = tmp / 16.0; // remove extra 4 bits, convert back to float
tmp = vtx1.y * 16; // increase by 4 bits, truncate off the rest
vtx1.y = tmp / 16.0; // remove extra 4 bits, convert back to float
tmp = vtx2.x * 16; // increase by 4 bits, truncate off the rest
vtx2.x = tmp / 16.0; // remove extra 4 bits, convert back to float
tmp = vtx2.y * 16; // increase by 4 bits, truncate off the rest
vtx2.y = tmp / 16.0; // remove extra 4 bits, convert back to float
tmp = vtx3.x * 16; // increase by 4 bits, truncate off the rest
vtx3.x = tmp / 16.0; // remove extra 4 bits, convert back to float
tmp = vtx3.y * 16; // increase by 4 bits, truncate off the rest
vtx3.y = tmp / 16.0; // remove extra 4 bits, convert back to float
/*o/ vtx1.a=220.0f;
vtx2.a=220.0f;
vtx3.a=220.0f;/**/
/**/ vtx1.a=255.0f;
vtx2.a=255.0f;
vtx3.a=255.0f;/**/
/* Make the alpha value (transparency) equal to the
colour at each vertex - the brighter it is, the
less transparent it is. Gives a nice 'glare' effect */
/* vtx1.a=(float)Object.Vertex[poly->Vertex[0]].color;
vtx2.a=(float)Object.Vertex[poly->Vertex[1]].color;
vtx3.a=(float)Object.Vertex[poly->Vertex[2]].color;/**/
vtx1.oow = -1.f/(float)Object.Vertex[poly->Vertex[0]].sz;
vtx2.oow = -1.f/(float)Object.Vertex[poly->Vertex[1]].sz;
vtx3.oow = -1.f/(float)Object.Vertex[poly->Vertex[2]].sz;
/*if (vtx1.x<-50.0|| vtx1.y <-50.0 ||
vtx1.x >690.0 || vtx1.y >520.0||
vtx2.x <-50.0 || vtx2.y <-50.0 ||
vtx2.x >690.0 || vtx2.y >530.0||
vtx3.x <-50.0 || vtx3.y <-50.0 ||
vtx3.x >690.0 || vtx3.y >530.0||*/
/*
if ( vtx1.oow <0.0 || vtx2.oow <0.0 || vtx3.oow <0.0)
return;*/
/*if (vtx1.oow <0.0 || vtx2.oow <0.0 || vtx3.oow <0.0)
return;*/
if (vtx1.oow <0.0) vtx1.oow = 0.9999;
if (vtx2.oow <0.0) vtx2.oow = 0.9999;
if (vtx3.oow <0.0) vtx3.oow = 0.9999;/**/
/**/
if (vtx1.x<1.0) vtx1.x = 1.0;
if (vtx1.x>640.0) vtx1.x = 640.0;
if (vtx1.y<1.0) vtx1.y = 1.0;
if (vtx1.y>480.0) vtx1.y = 480.0;
if (vtx2.x<1.0) vtx2.x = 1.0;
if (vtx2.x>640.0) vtx2.x = 640.0;
if (vtx2.y<1.0) vtx2.y = 1.0;
if (vtx2.y>480.0) vtx2.y = 480.0;
if (vtx3.x<1.0) vtx3.x = 1.0;
if (vtx3.x>640.0) vtx3.x = 640.0;
if (vtx3.y<1.0) vtx3.y = 1.0;
if (vtx3.y>480.0) vtx3.y = 480.0;/**/
/*
vtx1.tmuvtx[0].sow = 0.f * vtx1.oow;
vtx1.tmuvtx[0].tow = 0.f * vtx1.oow;
vtx2.tmuvtx[0].sow = 255.f * vtx2.oow;
vtx2.tmuvtx[0].tow = 255.f * vtx2.oow;
vtx3.tmuvtx[0].sow = 255.f * vtx3.oow;
vtx3.tmuvtx[0].tow = 0.f * vtx3.oow;
*/
if (mode == SURFACE)
{
vtx1.tmuvtx[0].sow =
(Object.Vertex[poly->Vertex[0]].s + 100.0*Object.Vertex[poly->Vertex[0]].Noz)
* vtx1.oow;
vtx1.tmuvtx[0].tow =
(Object.Vertex[poly->Vertex[0]].t + 100.0*Object.Vertex[poly->Vertex[0]].Noy)
* vtx1.oow;
vtx2.tmuvtx[0].sow =
(Object.Vertex[poly->Vertex[1]].s + 100.0*Object.Vertex[poly->Vertex[1]].Noz)
* vtx2.oow;
vtx2.tmuvtx[0].tow =
(Object.Vertex[poly->Vertex[1]].t + 100.0*Object.Vertex[poly->Vertex[1]].Noy)
* vtx2.oow;
vtx3.tmuvtx[0].sow =
(Object.Vertex[poly->Vertex[2]].s + 100.0*Object.Vertex[poly->Vertex[2]].Noz)
* vtx3.oow;
vtx3.tmuvtx[0].tow =
(Object.Vertex[poly->Vertex[2]].t + 100.0*Object.Vertex[poly->Vertex[2]].Noy)
* vtx3.oow;
}
else if (mode == BLOB)/* BLOB */
{
vtx1.tmuvtx[0].sow =
(Object.Vertex[poly->Vertex[0]].s + 100.00*
(Object.Vertex[poly->Vertex[0]].SNox-Object.Vertex[poly->Vertex[0]].Nox))
* vtx1.oow;
vtx1.tmuvtx[0].tow =
(Object.Vertex[poly->Vertex[0]].t + 100.0*
(Object.Vertex[poly->Vertex[0]].SNoy-Object.Vertex[poly->Vertex[0]].Noy))
* vtx1.oow;
vtx2.tmuvtx[0].sow =
(Object.Vertex[poly->Vertex[1]].s + 100.0*
(Object.Vertex[poly->Vertex[1]].SNox-Object.Vertex[poly->Vertex[1]].Nox))
* vtx2.oow;
vtx2.tmuvtx[0].tow =
(Object.Vertex[poly->Vertex[1]].t + 100.0*
(Object.Vertex[poly->Vertex[1]].SNoy-Object.Vertex[poly->Vertex[1]].Noy))
* vtx2.oow;
vtx3.tmuvtx[0].sow =
(Object.Vertex[poly->Vertex[2]].s + 100.0*
(Object.Vertex[poly->Vertex[2]].SNox-Object.Vertex[poly->Vertex[2]].Nox))
* vtx3.oow;
vtx3.tmuvtx[0].tow =
(Object.Vertex[poly->Vertex[2]].t + 100.0*
(Object.Vertex[poly->Vertex[2]].SNoy-Object.Vertex[poly->Vertex[2]].Noy))
* vtx3.oow;
}
else
{
vtx1.tmuvtx[0].sow = (Object.Vertex[poly->Vertex[0]].s) * vtx1.oow;
vtx1.tmuvtx[0].tow = (Object.Vertex[poly->Vertex[0]].t) * vtx1.oow;
vtx2.tmuvtx[0].sow = (Object.Vertex[poly->Vertex[1]].s) * vtx2.oow;
vtx2.tmuvtx[0].tow = (Object.Vertex[poly->Vertex[1]].t) * vtx2.oow;
vtx3.tmuvtx[0].sow = (Object.Vertex[poly->Vertex[2]].s) * vtx3.oow;
vtx3.tmuvtx[0].tow = (Object.Vertex[poly->Vertex[2]].t) * vtx3.oow;
}
/*if (Object.Vertex[poly->Vertex[2]].Noy != 0.0)
printf("nx ny nz %f %f %f\n",
Object.Vertex[poly->Vertex[2]].Nox,
Object.Vertex[poly->Vertex[2]].Noy,
Object.Vertex[poly->Vertex[2]].Noz);*/
#ifdef GO
/*guDrawTriangleWithClip( &vtx1, &vtx2, &vtx3 );*/
grDrawTriangle( &vtx1, &vtx2, &vtx3 );
#endif
return;
/* save state! Very inefficient way of doing this
should readly draw all basic texture polys first
and then draw them all using prjected texture
mapping. But I don't care :) */
grGlideGetState(&state);
/* My head hurts :( */
#ifdef GO
guColorCombineFunction(GR_COLORCOMBINE_ITRGB );
grAlphaCombine(GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_ONE,
GR_COMBINE_LOCAL_NONE,GR_COMBINE_OTHER_CONSTANT,
FXFALSE);
grAlphaBlendFunction(GR_BLEND_ONE,GR_BLEND_ONE,
GR_BLEND_ONE,GR_BLEND_ZERO);
grAlphaTestFunction( GR_CMP_ALWAYS );
grDrawTriangle( &vtx1, &vtx2, &vtx3 );
#endif
/* restore state */
grGlideSetState(&state);
}
/*---------------------------------------------------------------*/
int _cdecl main(int argc,char**argv)
{
int x,y;
int index=0;
system("del out\n");
fp=fopen("listval.txt","w");
setbuf(fp,0);
build_table();
build_itable();
/* set up Glide and the hardware */
screenRes = GR_RESOLUTION_640x480;
grSstQueryBoards(&hwconfig);
fprintf(stdout,"Number of boards = %d\n",hwconfig.num_sst);
fflush(stdout);
grGlideInit();
if ( !grSstQueryHardware( &hwconfig ) )
{
fprintf( stderr, "main: grSstQueryHardware failed!\n" );
grGlideShutdown();
exit( -1 );
}
grSstSelect( 0 );
if ( !grSstOpen( screenRes,
GR_REFRESH_75Hz,
GR_COLORFORMAT_ARGB,
GR_ORIGIN_LOWER_LEFT,
GR_SMOOTHING_ENABLE,
2 ) )
{
fprintf( stderr, "main: grSstOpen failed!\n" );
grGlideShutdown();
exit( -1 );
}
printf("Gouraud Shaded Vectors 2\n");
strcpy(filename,"diamond.v10");
max = 99999;
if (argc>1) max = atoi(argv[1]);
printf("max=%d\n",max);
guColorCombineFunction( GR_COLORCOMBINE_ITRGB );
guAlphaSource( GR_ALPHASOURCE_ITERATED_ALPHA );
grAlphaBlendFunction( GR_BLEND_SRC_ALPHA,
GR_BLEND_ONE_MINUS_SRC_ALPHA,
GR_BLEND_ONE,
GR_BLEND_ZERO );
grAlphaTestFunction( GR_CMP_ALWAYS );
/*bench(); /* noddy benchmark procedure - ignore
grBufferClear( 0x000000, 0, GR_WDEPTHVALUE_FARTHEST );
grBufferSwap(0);
grBufferClear( 0x000000, 0, GR_WDEPTHVALUE_FARTHEST );*/
/*
image0 - dots
image1 -
image2 - BW
image3 -
image4 - dunes
image5 moon
*/
/* Texture for CHROME surface */
Load3dfxTexture("image0.3df",&texture1);
Load3dfxTexture("image1.3df",&texture2);
Load3dfxTexture("image2.3df",&texture3);
Load3dfxTexture("image3.3df",&texture4);
Load3dfxTexture("image4.3df",&texture5);
Load3dfxTexture("image5.3df",&texture6);
/* point object and background textures at some defaults */
fgtexture = &texture4;
bgtexture = &texture4;
/* Texture for MASK surface */
Load3dfxTexture("facehi.3df",&facetexture);
Load3dfxTexture("spot.3df",&spotlight);
Demo();
grGlideShutdown();
return(0);
}
void
ChangeTextures ()
{
switch(rand()%6)
{
case 0:
fgtexture = &texture1;
break;
case 1:
fgtexture = &texture2;
break;
case 2:
fgtexture = &texture3;
break;
case 3:
fgtexture = &texture4;
break;
case 4:
fgtexture = &texture5;
break;
case 5:
fgtexture = &texture6;
break;
default:;
}
bgtexture = fgtexture;
}
void Demo(void)
{
int i;
int frames = 0;
int count=0;
int next;
long int tim;
double vel = 4.0;
int level = 1;
mode = SURFACE ;
ClearVertexList();
Random();
srand( (unsigned)time( NULL ) );
init();
printf("init norms\n");
InitNormals();
FInitNormals();
/* initialize a few things*/
printf("initialize a few things\n");
InitYTable();
InitTrigTables();
InitLightSource();
/* initialize angle and position of object*/
xangle=0; yangle=80/*64*/; zangle=256;
zpos=-1024.0;
zpos=-512.0;
zpos=-10.25;
cx = 31 ; cy = 20; cz = 0;
/* draw first frame so that globe won't "pop out of nowhere" (:*/
MakeViewPolygonList();
RotatePoints();
RotateNormals();
DrawObject();
tim=clock();
next = 200;
/*mode = CMASK;DoFace();yangle=0;cx=0;*/
/*if (rand()%2) mode = MASK;*/
/*mode = BLOB; DoSphere(5);*/
do
{
if (mode == SURFACE || mode == BLOB)
calcFc (mode);
MakeViewPolygonList();
RotatePoints();
FInitNormals();
if (mode == MASK)
RotateNormals; /* copy out for chrome face */
DrawObject();
swapbuffer();
xangle++; xangle = xangle % MAXDEGREES;
cy = cosine[(MAXDEGREES-xangle)%MAXDEGREES] * 60;
cz = sine[(MAXDEGREES-xangle)%MAXDEGREES] * 60;
frames++;
/**/
if (frames % (mode==CMASK?800:1200)==0)
{
init ();
if (mode == SURFACE)
{
ChangeTextures();
mode = BLOB;
DoSphere(4+rand()%1);
}
else if (mode == BLOB)
{
ChangeTextures();
yangle=0;cx=0;
DoFace();
mode = CMASK;
if (rand()%8 == 0) mode = MASK;
}
else
{
ChangeTextures();
yangle=80;cx=31;
mode = SURFACE;
Random();
}
}
/**/
if (frames % next == 0)
{
V[rand()%WATER][rand()%WATER] = rand()%7+8;
next = rand()%14;
next = next*next+100;
Vb[rand()%Object.NumOfVertices] = rand()%7;
}
} while(frames < max && !kbhit());
tim=clock()-tim;
printf("Elapsed = %lf seconds\n",(double)(tim)/CLOCKS_PER_SEC);
printf("FPS = %lf \n",(double)frames/
((double)(tim)/CLOCKS_PER_SEC));
}
int
sleep(int x)
{
long int tim;
tim = clock();
while (clock() < tim+x) ;
return(0);
}
void MakeCulledPolygonList()
{
int i,j;
VertexTYPE *v0,*v1,*v2;
j=0;
for(i=0;i<NumOfViewedPolygons;i++)
{
v0=&Object.Vertex[Object.Polygon[PolygonViewList[i]].Vertex[0]];
v1=&Object.Vertex[Object.Polygon[PolygonViewList[i]].Vertex[1]];
v2=&Object.Vertex[Object.Polygon[PolygonViewList[i]].Vertex[2]];
/* if expression results in a negative then polygon is visible*/
if( ((v1->sx-v0->sx) * (v2->sy-v0->sy) - (v1->sy - v0->sy)
*(v2->sx-v0->sx)) > 0 || mode == MASK || mode == CMASK)
{
PolygonOrderList[j++] =PolygonViewList[i];
}
}
NumOfSortedPolygons=j;
}
void SortPolygonList()
{
int i,j;
int maxz,minz;
PolygonTYPE *poly;
/* first find the distance of each polygon (from midpoint of max & min z's)*/
for(i=0;i<Object.NumOfPolygons;i++)
{
poly=&Object.Polygon[i];
minz=65535;
maxz=-65536;
for(j=0;j<poly->NumOfVertices;j++)
{
if(Object.Vertex[poly->Vertex[j]].sz < minz)
{
minz=Object.Vertex[poly->Vertex[j]].sz;
}
if(Object.Vertex[poly->Vertex[j]].sz > maxz)
{
maxz=Object.Vertex[poly->Vertex[j]].sz;
}
}
/* now calculate the distance*/
poly->zcenter=(maxz+minz)<<1;
}
/* qsort the polygons*/
qsort(PolygonOrderList,NumOfSortedPolygons,sizeof(int),ComparePolygons);
/* all done the sorting process*/
}
int _cdecl ComparePolygons(const void *a, const void *b)
{
if( Object.Polygon[*(int *)a].zcenter < Object.Polygon[*(int *)b].zcenter )
{
return -1;
}
else if( Object.Polygon[*(int *)a].zcenter >
Object.Polygon[*(int *)b].zcenter )
{
return +1;
}
else
{
return 0;
}
}
/*-------------------------- inilialize light source -----------------------*/
void InitLightSource(void)
{
double xlen,ylen,zlen,length;
/* assign the delault light source position*/
xlen=-10; ylen=-10; zlen=-10;
/* calculate the length of the vector (light source to 0,0,0)*/
length = sqrt(xlen*xlen + ylen*ylen + zlen*zlen);
/* scale it to a unit vector*/
LightSource.x = (xlen/length);
LightSource.y = (ylen/length);
LightSource.z = (zlen/length);
}
/*==========================================================*/
int
Visible(double tx, double ty)
{
if (lsign*(axl*tx-byl*ty-cl) > 0.0 &&
rsign*(axr*tx-byr*ty-cr) < 0.0)
return(1);
else
return(0);
}
int qabs(int x)
{
int copy = x >>31;
x ^= copy;
return x-copy;
}
void MakeViewPolygonList()
{
int i,j;
VertexTYPE *v0,*v1,*v2;
theta = (256+512+xangle)%MAXDEGREES;
CalcViewTriangle(cz,cy,theta);
j=0;
for(i=0;i<Object.NumOfPolygons;i++)
{
v0=&Object.Vertex[Object.Polygon[i].Vertex[0]];
v1=&Object.Vertex[Object.Polygon[i].Vertex[1]];
v2=&Object.Vertex[Object.Polygon[i].Vertex[2]];
if ((lsign*(axl*v1->oz-byl*v1->oy-cl) > 0.0 &&
rsign*(axr*v1->oz-byr*v1->oy-cr) < 0.0) ||
(lsign*(axl*v2->oz-byl*v2->oy-cl) > 0.0 &&
rsign*(axr*v2->oz-byr*v2->oy-cr) < 0.0) ||
(lsign*(axl*v0->oz-byl*v0->oy-cl) > 0.0 &&
rsign*(axr*v0->oz-byr*v0->oy-cr) < 0.0))
PolygonViewList[j++]=i;
if ((lsign*(axl*v1->oz-byl*v1->oy-cl) < 0.0 ||
lsign*(axl*v2->oz-byl*v2->oy-cl) < 0.0 ||
lsign*(axl*v0->oz-byl*v0->oy-cl) < 0.0 ) &&
(rsign*(axr*v1->oz-byr*v1->oy-cr) > 0.0 ||
rsign*(axr*v2->oz-byr*v2->oy-cr) > 0.0 ||
rsign*(axr*v0->oz-byr*v0->oy-cr) > 0.0 ) &&
(fsign*(axf*v1->oz-byf*v1->oy-cf) < 0.0 ||
fsign*(axf*v2->oz-byf*v2->oy-cf) < 0.0 ||
fsign*(axf*v0->oz-byf*v0->oy-cf) < 0.0 ))
{
PolygonViewList[j++]=i;
}
/*
if (fsign*(axf*v1->oz-byf*v1->oy-cf) < 0.0 ||
fsign*(axf*v2->oz-byf*v2->oy-cf) < 0.0 ||
fsign*(axf*v0->oz-byf*v0->oy-cf) < 0.0 )
{
PolygonViewList[j++]=i;
printf("FRONT\n");
}*/
}
NumOfViewedPolygons=j;
}
void
CalcViewTriangle(double cx, double cy, int theta)
{
/* hmm step back a bit...
double mcx,mcy;
cx = -10.5*dcosine[theta]+cx;
cy = -10.5*dsine[theta]+cy; */
/* Set up left and right view edges */
rtheta = (theta+(MAXDEGREES-FOV))%MAXDEGREES;
ltheta = (theta+FOV)%MAXDEGREES;
ftheta = (theta+(MAXDEGREES/4))%MAXDEGREES;
/* Line Equation = */
if (qabs(256-ltheta)>128 && /* nearer x-axis */
qabs(768-ltheta)>128)
{
axl = polar_lut[ltheta]; byl = 1.0; cl = (cx*axl-cy);
}
else
{
axl= 1.0; byl = polar_lut[ltheta]; cl = (cx - cy*byl);
}
if (qabs(256-rtheta)>128 && /* nearer x-axis */
qabs(768-rtheta)>128)
{
axr = polar_lut[rtheta]; byr = 1.0; cr = (cx*axr-cy);
}
else
{
axr = 1.0; byr = polar_lut[rtheta]; cr = (cx - cy*byr);
}
if (qabs(256-ftheta)>128 && /* nearer x-axis */
qabs(768-ftheta)>128)
{
axf = polar_lut[ftheta]; byf = 1.0; cf = (cx*axf-cy);
}
else
{
axf = 1.0; byf = polar_lut[ftheta]; cf = (cx - cy*byf);
}
tpx = 10.0*dcosine[theta]+cx;
tpy = 10.0*dsine[theta]+cy;
if (axl*tpx-byl*tpy-cl > 0.0) lsign = 1.0;
else lsign = -1.0;
if (axr*tpx-byr*tpy-cr < 0.0) rsign = 1.0;
else rsign = -1.0;
if (axf*tpx-byf*tpy-cf < 0.0) fsign = 1.0;
else fsign = -1.0;
}